/**
 * Created by macos on 14/10/27.
 */

var domain = require('domain');
var EventEmitter = require('events').EventEmitter;
var net = require('net');
var util = require('util');

// var assert = require('assert-plus');
var _ = require('lodash');

var MessageDecoder = require('./messageDecoder').MessageDecoder;
var MessageEncoder = require('./messageEncoder').MessageEncoder;

var slice = Function.prototype.call.bind(Array.prototype.slice);

(function() {

	var root = this;

	function Server(config) {
		EventEmitter.call(this);

		var self = this;
		self._config = config || {};
		self._protocols = [];

		this.srv = net.createServer(this.onConnection.bind(this)); //通过bind将onConnection函数传入

		//复制srv的属性到Server
		_.forEach(['connections', 'maxConnections', 'localAddress', 'localPort'], function(property) {
			self.__defineSetter__(property, function(v) {
				self.srv[property] = v;
			});
			self.__defineGetter__(property, function() {
				return (self.srv[property]);
			});
		});

		//复制srv的事件到Server
		_.forEach(['close', 'connection', 'error', 'listening'], function(event) {
			self.srv.on(event, function() {
				var args = slice(arguments);
				args.unshift(event);
				self.emit.apply(self, args);
			});
		});
	}
	util.inherits(Server, EventEmitter);

	//复制srv的方法到Server
	_.forEach(['close', 'listen', 'address'], function(method) {
		Server.prototype[method] = function() {
			this.srv[method].apply(this.srv, arguments);
		};
	});

	/**
	 * 客户端连接处理。可以查看net.socket
	 * @param conn
	 */
	Server.prototype.onConnection = function onConnection(conn) {
		sails.log.debug("Server.onConnection");

		conn.setTimeout(this._config.clientTimeout);

		var self = this;
		var decoder = new MessageDecoder();
		var encoder = new MessageEncoder(conn);
		var protocols = self._protocols; //为保证异步下可调用，必须赋值到当前变量中。

		encoder.isConnected(true);
		self.emit('clientConnection', encoder);

		conn.on('close', function(err) {
			encoder.isConnected(false);
		});

		conn.on('data', function(data) {
			decoder.decode(protocols, data);
		});

		decoder.on('decode', function(error, msg) {
			if (error) {
				if (_.has(error, 'event')) {
					self.emit(error.event, error, null, encoder);
				}

				if (EventEmitter.listenerCount(self, 'error') > 0) {
					self.emit('error', error);
				}

			} else {
				self.emit(msg.event, null, msg, encoder);
			}
		});

		decoder.on('protocolError', function(e) {
			if (EventEmitter.listenerCount(encoder, 'error') > 0) {
				encoder.emit('error', e);
			}
		});

	};

	Server.prototype.onMessage = function onMessage(protocol, cb) {
		//    console.log("Server.onMessage:", protocol);

		var self = this;
		var cb = cb || function() {};

		//校验协议protocol
		if (!protocol.event) {
			throw new Error("'Event' is not existed or on 1rt");
		}

		var i = 0;
		_.forEach(protocol, function(v, k) {
			if (i === 0) {
				if (!_.isString(protocol.event)) {
					//协议校验错误，直接抛出
					throw new Error("The type of 'event' must is String");
				}
			} else {

				if (!((_.isString(v)) || (_.isNumber(v)) || (_.isFunction(v)))) {
					var error = new Error("The type of '" + k + "' must is function or number or hex string ");
					throw error;
				}
			}
			i++;
		});

		//添加协议
		this._protocols.push(protocol);

		//响应协议中的事件
		this.on(protocol.event, function(error, msg, encoder) {
			process.nextTick(function() {
				cb(error, msg, encoder);
			});
		});

		return (this);
	}

	//防止异常中断服务器运行
	//	process.on('uncaughtException', function(err) {
	//		console.log('Caught exception: ' + err);
	//	});

	module.exports = {
		createServer: function createServer(config) {
			return (new Server(config));
		}
	};
})();